import 'dart:io';

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hygf/http/DioClient.dart';
import 'package:hygf/http/file_transfer/down_cap.dart';
import 'package:hygf/http/file_transfer/upload_cap.dart';
import 'package:hygf/http/file_transfer/upload_request_option.dart';
import 'package:hygf/res/my_colors.dart';
import 'package:hygf/util/LoadingUtils.dart';
import 'package:hygf/view/dialog/dialog_manager.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
import '../http/file_transfer/upload_result.dart';
import '../res/HDColors.dart';
import 'camera/camera_page.dart';
import 'image_preview_page.dart';
import 'package:path_provider/path_provider.dart';

/// 照片选择器部件
/// 可以单独作为widget使用 也可以作为media editor的一部分
/// Created by LY
/// Update on 2022.7.3 修改照片选择器数据列表格式 从原来的String list改为ImagePickerData list。
/// Update on 2022.7.7 控制器增加resetImages方法 用来重置照片列表 主要用于上传以后刷新
/// Update on 2022.7.11 照片选择器改为自带上传功能
/// Update on 2022.11.2 增加照片选择方式的参数，默认拍照、从相册选择2种
class ImagePickerWidget extends StatefulWidget {
  ImagePickerWidgetController controller;
  bool? readonly = false;
  bool isAsync = false;
  int crossAxisCount;

  List<dynamic>? chooseItems;

  ImagePickerWidget(
      {Key? key,
      required this.controller,
      this.readonly,
      this.crossAxisCount = 4,
      this.isAsync = false,
      this.chooseItems = const [
        {"name": "拍照", "code": "photo"},
        {"name": "从相册选择", "code": "album"}
      ]})
      : super(key: key);

  @override
  _ImagePickerWidgetState createState() => _ImagePickerWidgetState();
}

class _ImagePickerWidgetState extends State<ImagePickerWidget> {
  bindController() {
    widget.controller._state = this;
  }

  @override
  void initState() {
    bindController();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    // 过滤数据 把标记为已删除的数据删掉
    List<ImagePickerData> filterData =
        widget.controller.data.where((element) => !element.isDel).toList();
    widget.controller.data = filterData;
    if(_notImage(filterData)){
      return  Column(
        children: [
             ...filterData.map((item) => downFileWidget(item)).toList(),
        ],
      );

    }else{
      return (filterData.length == 0 && widget.readonly == true)
        ? Container()
        : Container(
            padding: EdgeInsets.all(8),
            child: GridView.builder(
              shrinkWrap: true,
              physics: NeverScrollableScrollPhysics(),
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: widget.crossAxisCount,
                mainAxisSpacing: 8,
                crossAxisSpacing: 8,
                childAspectRatio: 1,
              ),
              itemBuilder: (context, index) {
                if (index == filterData.length && widget.readonly != true) {
                  return GestureDetector(
                    onTap: () {
                      if (!(widget.readonly ?? false)) {
                        _showActionSheet();
                      }
                    },
                    child:
                        Image.asset("assets/images/image_picker_camera.webp"),
                  );
                }
                return GestureDetector(
                  onTap: () {
                    // setState(() {
                    //   list.removeAt(index);
                    // });
                    Get.to(ImagePreviewPage(data: filterData));
                  },
                  child: Stack(
                    children: [
                      Container(
                        width: double.infinity,
                        height: double.infinity,
                        child: _getImageFromPath(filterData[index].filePath),
                      ),
                      widget.readonly == true
                          ? const SizedBox(
                              width: 0,
                              height: 0,
                            )
                          : Positioned(
                              width: 32,
                              height: 32,
                              right: 2,
                              top: 2,
                              child: GestureDetector(
                                onTap: () {
                                  setState(() {
                                    filterData[index].isDel = true;
                                  });
                                },
                                child: Container(
                                  color: Colors.transparent,
                                  padding:
                                      EdgeInsets.only(left: 16, bottom: 16),
                                  child: Image.asset(
                                      "assets/images/media_editor_asset_delete.webp"),
                                ),
                              ),
                            ),
                    ],
                  ),
                );
              },
              itemCount: widget.readonly == true
                  ? filterData.length
                  : filterData.length + 1,
            ),
          );
    }
  }

  _notImage(List<ImagePickerData> filterData){
    for (var item in filterData) {
      if (!isImageFile(item.fileName)) {
        return true;
      }
    }
    return false;
  }

  _showActionSheet() async {
    _hdFocusNode();
    var map = await DialogManager.showActionSheet(
        items: widget.chooseItems ?? [], title: "请选择");
    if (map == null) {
      return;
    }
    switch (map["code"] ?? "") {
      case "photo":
        // 拍照
        var result = await Get.to(CameraPage(
          cameraType: CameraType.IMAGE,
        ));
        if (result != null && result is String) {
          var success = await _uploadFiles(
              [ImagePickerData(result.split("/").last, result)]);
          setState(() {
            widget.controller.data.addAll(success);
          });
        }
        break;
      case "album":
        if (mounted) {
          var result = await AssetPicker.pickAssets(
            context,
            pickerConfig: AssetPickerConfig(
                themeColor: MyColors.accent,
                textDelegate: AssetPickerTextDelegate(),
                requestType: RequestType.image),
          );
          if (result != null && result.isNotEmpty) {
            List<ImagePickerData> req = [];
            for (var item in result) {
              File? file = await item.originFile;
              if (file != null) {
                req.add(ImagePickerData(file.path.split("/").last, file.path));
              }
            }
            var res = await _uploadFiles(req);
            widget.controller.data.addAll(res);
            setState(() {});
          }
        }
        break;
      default:
    }
  }

  ///表示处理隐藏键盘
  _hdFocusNode() {
    FocusScope.of(context).requestFocus(FocusNode());
  }

  Future<List<ImagePickerData>> _uploadFiles(
      List<ImagePickerData> dataList) async {
    List<BaseUploadRequestOption> files = [];
    for (var value in dataList) {
      if (value.isInit || value.isDel) {
        break;
      }
      files.add(FileUploadRequestOption(
          type: UploadFileType.media,
          filePath: value.filePath,
          keepFileName: true));
    }

    int failedCount = 0;
    int successCount = 0;
    List<ImagePickerData> successImages = [];
    LoadingUtils.loading(
      status: "上传中...",
    );
    try {
      await DioClient().uploadFiles(files,
          isAsync: widget.isAsync,
          hideLoading: true, progressListener: (response, i, t) {
        if (response?.isok != true) {
          failedCount++;
        } else {
          successCount++;
          successImages.add(ImagePickerData(
              (response!.data as UploadResult).fileName ?? "",
              (response.data as UploadResult).filePath ?? "",
              name: (response.data as UploadResult).fileName,
              id: (response.data as UploadResult).id));
        }
      });
      LoadingUtils.dismiss();
      if (failedCount != 0) {
        LoadingUtils.AlertDialog("上传成功$successCount张，失败$failedCount张");
      }
    } catch (e) {
      LoadingUtils.dismiss();
    }
    return successImages;
  }

  _getImageFromPath(String path) {
    if (path.isEmpty) {
      return Image.asset("assets/images/image_picker_placehold.webp");
    } else if (path.startsWith("http://") || path.startsWith("https://")) {
      // 如果地址以http或https开头 就认为他是网络地址
      return FadeInImage.assetNetwork(
        placeholder: "assets/images/image_picker_placehold.webp",
        image: path,
        fit: BoxFit.cover,
        imageErrorBuilder: (context, error, stackTrace) {
          return Image.asset("assets/images/image_picker_placehold.webp");
        },
      );
    } else {
      return Image.file(File(path), fit: BoxFit.cover);
    }
  }

  downFileWidget(ImagePickerData item) {
     return InkWell(
        onTap: () async {
           var extPath = await getExternalCacheDirectories();
              if (extPath == null || extPath.isEmpty) {
                LoadingUtils.showError("该设备没有可存储文件的目录，无法下载升级");
                return;
              }
              var tempPath = "${extPath[0].path}/hygf/${item.fileName}";
              bool success = await DioClient().down(
              url: item.filePath,
              path: tempPath,
              onProgress: (_progress) {
                // LoadingUtils.showToast("下载进度${_progress}");
              });
              if(success){
                LoadingUtils.showToast("下载成功");
              }else{
                LoadingUtils.showToast("下载失败");
              }
        },
        child: Text(item.fileName,style: TextStyle(
                      fontSize: 16,
                      color: HDColors.blue,
                      fontWeight: FontWeight.w600)),
      );
  }
}

bool isImageFile(String fileName) {
  final imageExtensions = {
    '.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.tiff', '.webp'
  };
  final fileExtension = fileName.substring(fileName.lastIndexOf('.')).toLowerCase();
  return imageExtensions.contains(fileExtension);
}

/// 照片选择器控制器 用来添加和获取数据
class ImagePickerWidgetController {
  List<ImagePickerData> data = [];

  /// 通过控制器获取照片选择器的数据
  /// 如果是传进来的数据 全部传回去 已经删掉的 打标记为isDel = true
  /// 如果是选择器内部新增出来的数据 已经删掉的不回传
  List<ImagePickerData> getImages() {
    // 不是传进来的 并且已经被删掉了 就不返回了
    return data
        .where((element) => !(!element.isInit && element.isDel))
        .toList();
  }

  _ImagePickerWidgetState? _state;

  /// 添加照片
  /// 外部添加的照片选择器会自动打标记为isInit = true
  Future<void> addImages(List<ImagePickerData> data) async {
    for (var value in data) {
      if (value.filePath.isEmpty) {
        value.filePath = DioClient().getPreviewUrlSync(value.fileName);
      }
    }

    // 传入的数据 标记为init的
    for (var element in data) {
      element.isInit = true;
    }
    this.data.addAll(data);
    // 判断控件如果已经准备就绪 就刷新控件
    if (_state?.mounted == true) {
      _state?.setState(() {});
    }
  }

  void resetImages(List<ImagePickerData> data) {
    this.data.clear();
    addImages(data);
  }
}

/// 照片选择器需要的数据源格式
class ImagePickerData {
  String? name = ""; //文件名字
  String fileName = "";
  String filePath = "";
  bool isInit = false;
  bool isDel = false;
  int? id;
  String extension = "";

  /// fileName 照片名称 如果是对象存储的数据 照片名称为对象存储的位置 如果是本地图片 照片名称是文件名
  /// filePath 照片路径 如果是对象存储的数据 照片路径是对象存储的预览url 如果是本地图片 照片路径是文件地址
  ImagePickerData(this.fileName, this.filePath, {this.name, this.id});

  ImagePickerData.fromJson(Map<String, dynamic> json) {
    fileName = json['fileName'] ?? "";
    filePath = json['filePath'] ?? "";
    name = json['name'] ?? "";
    isInit = json['isInit'] ?? false;
    isDel = json['isDel'] ?? false;
    id = json['id'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = Map<String, dynamic>();
    data['fileName'] = fileName;
    data['filePath'] = filePath;
    data['name'] = name;
    data['isInit'] = isInit;
    data['isDel'] = isDel;
    data['id'] = this.id;
    return data;
  }
}
